﻿using System;
using SharpStockLib.Fin;

namespace SharpStockLib.Net
{
    /// <summary>
    /// Helper class to download historical (and maybe real-time ?) quotes from Yahoo Finance.
    /// </summary>
    public class YahooDownloader : Downloader
    {
        // TODO: To update quotes, consider using http://finance.yahoo.com/d/quotes.csv?s=XOM&f=snol1hgvx
        private const string yahooBaseUri = "http://ichart.finance.yahoo.com/table.csv?";
        private readonly string _outputFolder;

        public YahooDownloader(string outputFolder)
        {
            _outputFolder = outputFolder;

            if(!outputFolder.EndsWith("\\"))
                _outputFolder += "\\";
        }

        public string OutputFolder
        {
            get
            {
                return _outputFolder;
            }
        }

        /// <summary>
        /// Downloads the appropriate CSV for the given stock from the Yahoo website for the input dates.
        /// </summary>
        /// <param name="stock">The stock to download the EOD data for. Only the symbol is required.</param>
        /// <param name="startDate">The date from which the data must be retrieved. Can be null, in which case the default will be "05/06/1998" (June 5th 1998), which is the oldest date Yahoo can get data for anyway.</param>
        /// <param name="endDate">The date until which the data must be retrieved. Can be null, in which case the default will be today.</param>
        /// <returns></returns>
        public DownloadResult Download(Stock stock, DateTime? startDate, DateTime? endDate)
        {
            if (stock == null)
                throw new ArgumentNullException("stock", "Stock cannot be null. Please specify a stock.");

            // Default values : start date = 05/06/1998 (Yahoo does not have older quotes) and end date = today.
            if (startDate == null)
                startDate = new DateTime(1998, 6, 5);
            if (endDate == null)
                endDate = DateTime.Today;

            // Builds appropriate URI
            Uri fileToGet = BuildURI(stock.Symbol, (DateTime)startDate, (DateTime)endDate);

            // Builds the output path
            string outputPath = _outputFolder + stock.Symbol + ".csv";

            YahooResult res = new YahooResult(Download(fileToGet, outputPath));
            res.Stock = stock;

            return res;
        }

        /// <summary>
        /// Builds the URI to get the data from by using Yahoo's format.
        /// </summary>
        /// <param name="symbol">The ticker of the stock to get quotes for.</param>
        /// <param name="startDate">Starting date of the historical period to get quotes for</param>
        /// <param name="endDate">End date of the historical period to get quotes for</param>
        /// <returns>An URI that can be used later on to get the quotes.</returns>
        private Uri BuildURI(string symbol, DateTime startDate, DateTime endDate)
        {
            if (startDate == null)
                throw new ArgumentNullException("startDate", "Start date cannot be null. Please specify a start date.");
            if(endDate == null)
                throw new ArgumentNullException("endDate", "End date cannot be null. Please specify an end date.");
            if(string.IsNullOrEmpty(symbol))
                throw new ArgumentNullException("symbol", "Symbol cannot be null. Please specify a symbol.");

            string args = "s=" + symbol + "&a=" + (startDate.Month - 1) + "&b=" + startDate.Day + "&c=" + startDate.Year + "&d=" + (endDate.Month - 1) + "&e=" + endDate.Day + "&f=" + endDate.Year + "&g=d";
            return new Uri(yahooBaseUri + args);
        }
    }
}
